home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / mac / Technical Documentation / Develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15.sea / Scriptable Database 1.0a15 / Blue / ThreadContext.cp / ThreadContext.cp
Encoding:
Text File  |  1996-02-20  |  5.7 KB  |  185 lines  |  [TEXT/CWIE]

  1.  
  2. #include "ThreadContext.h"
  3.  
  4. #include "Exceptions.h"
  5.  
  6. #if 0
  7. #if __MWERKS__
  8. extern void* __local_destructor_chain;
  9. #endif
  10. #endif
  11.  
  12. //
  13. // Count of threads that have been created or are blocked
  14. // fCreatedThreads is counted by the TThreadContext constructor/destructor.
  15. // fSleepingThreads is counted by SwapIn/SwapOut (and fixed up by the destructor
  16. // if a sleeping thread is deleted)
  17. //
  18. long TThreadContext::fCreatedThreads = 0;
  19. long TThreadContext::fSleepingThreads = 0;
  20.  
  21. TThreadContext::TThreadContext(long threadCreateRefcon) :
  22.  
  23. #if 0
  24.                     fExceptionStack(nil),
  25. #if __MWERKS__
  26.                     fLocalDestructorChain(nil),
  27. #endif
  28. #endif
  29.                     fThreadCreateRefcon(threadCreateRefcon),
  30.                     fSleeping(false)
  31. {
  32.     ++fCreatedThreads;
  33.  
  34.     // set up interface to C++ exception runtime support
  35.     __new_exception_state(&fExceptionStack, fCatchBuffer, sizeof(fCatchBuffer));
  36. };
  37.  
  38. //----------------------------------------------------------------------------------------
  39. // TThreadContext::SwapIn
  40. //----------------------------------------------------------------------------------------
  41. void TThreadContext::SwapIn(ThreadID /*threadID*/)
  42. {
  43.     
  44.     ExceptionState    dummy;
  45.     __switch_exception_state(&fExceptionStack, &dummy);
  46.  
  47. #if 0    
  48.     gExceptionStack = fExceptionStack;
  49. #if __MWERKS__
  50.     __local_destructor_chain = fLocalDestructorChain;
  51. #endif
  52. #endif
  53.  
  54.     //
  55.     // If we were asleep at swapout time, then we
  56.     // are awake now; adjust the sleeping thread count.
  57.     //
  58.     if(fSleeping)
  59.     {
  60.         fSleeping = false;
  61.         --fSleepingThreads;
  62.     }
  63. }
  64.  
  65. //----------------------------------------------------------------------------------------
  66. // TThreadContext::SwapOut
  67. //----------------------------------------------------------------------------------------
  68. void TThreadContext::SwapOut(ThreadID threadID)
  69. {
  70.     __switch_exception_state(&fExceptionStack, &fExceptionStack);
  71.  
  72. #if 0
  73.     fExceptionStack = gExceptionStack;
  74. #if __MWERKS__
  75.     fLocalDestructorChain = __local_destructor_chain;
  76. #endif
  77. #endif
  78.  
  79.     ThreadState threadState;
  80.     if(GetThreadState(threadID, &threadState) == noErr)
  81.     {
  82.         //
  83.         // I'm not sure if the thread state is 'ready'
  84.         // or 'running' in the swap out handler, but it's
  85.         // probably 'ready'.  Anyway, we assume that
  86.         // 'stopped' is the only state a sleeping thread
  87.         // will be in.
  88.         //
  89.         fSleeping = (threadState == kStoppedThreadState);
  90.         if(fSleeping)
  91.         {
  92.             ++fSleepingThreads;
  93.         }
  94.     }
  95. }
  96.  
  97. //----------------------------------------------------------------------------------------
  98. // TThreadContext::DisposeContext
  99. //----------------------------------------------------------------------------------------
  100. void TThreadContext::DisposeContext(ThreadID /*threadID*/)
  101. {
  102.     delete this;
  103. }
  104.  
  105. //----------------------------------------------------------------------------------------
  106. // SwapThreadContextIn
  107. //----------------------------------------------------------------------------------------
  108. pascal void SwapThreadContextIn(ThreadID thread, void* refCon)
  109. {
  110.     TThreadContext* threadContext = (TThreadContext*) refCon;
  111.     threadContext->SwapIn(thread);
  112. }
  113.  
  114. //----------------------------------------------------------------------------------------
  115. // SwapThreadContextOut
  116. //----------------------------------------------------------------------------------------
  117. pascal void SwapThreadContextOut(ThreadID thread, void* refCon)
  118. {
  119.     TThreadContext* threadContext = (TThreadContext*) refCon;
  120.     threadContext->SwapOut(thread);
  121. }
  122.  
  123. //----------------------------------------------------------------------------------------
  124. // DestroyThreadContext
  125. //----------------------------------------------------------------------------------------
  126. pascal void DestroyThreadContext(ThreadID thread, void* refCon)
  127. {
  128.     TThreadContext* threadContext = (TThreadContext*) refCon;
  129.     threadContext->DisposeContext(thread);
  130. }
  131.  
  132. //----------------------------------------------------------------------------------------
  133. // ThreadCreateNotifyHandler
  134. //----------------------------------------------------------------------------------------
  135. pascal OSErr ThreadCreateNotifyHandler(ThreadID createdThread, long threadCreateRefcon)
  136. {
  137.     TThreadContext* threadContext = new TThreadContext(threadCreateRefcon);
  138.     
  139.     SetThreadSwitcher(createdThread, SwapThreadContextIn, (void*) threadContext, true);
  140.     SetThreadSwitcher(createdThread, SwapThreadContextOut, (void*) threadContext, false);
  141.     SetThreadTerminator(createdThread, DestroyThreadContext, (void*) threadContext);
  142.     
  143.     return noErr;
  144. }
  145.  
  146. //----------------------------------------------------------------------------------------
  147. // NewThreadWithNotification
  148. //
  149. // This routine calls 'NewThread', then notifies the application of what it has done
  150. //----------------------------------------------------------------------------------------
  151. OSErr NewThreadWithNotification(ThreadStyle threadStyle, ThreadEntryProcPtr threadEntry, void *threadParam, Size stackSize, ThreadOptions options, void **threadResult, ThreadID *threadMade, long threadCreateRefcon)
  152. {
  153.     OSErr err = noErr;
  154.     
  155.     err = NewThread(threadStyle, threadEntry, threadParam, stackSize, options, threadResult, threadMade);
  156.     if(err == noErr)
  157.         err = ThreadCreateNotifyHandler(*threadMade, threadCreateRefcon);
  158.     
  159.     return err;
  160. }
  161.  
  162. //----------------------------------------------------------------------------------------
  163. // ThreadCreateHandler
  164. //----------------------------------------------------------------------------------------
  165. pascal OSErr ThreadCreateHandler(ThreadEntryProcPtr threadEntry, void *threadParam, long handlerRefCon, ThreadID *threadMade)
  166. {
  167.     Size stackSize = 0;
  168.     ThreadOptions options = kCreateIfNeeded | kFPUNotNeeded;
  169.     
  170.     OSErr theErr = NewThread(
  171.         kCooperativeThread,
  172.         threadEntry,
  173.         threadParam,
  174.         stackSize,
  175.         options,
  176.         nil,
  177.         threadMade);
  178.     
  179.     if(theErr == noErr)
  180.         theErr = ThreadCreateNotifyHandler(*threadMade, handlerRefCon);
  181.  
  182.     return theErr;
  183. }
  184.  
  185.